package edu.tyut.game.ui.game

import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import edu.tyut.game.GameApplication
import edu.tyut.game.R
import edu.tyut.game.databinding.ActivityFlowerBinding
import edu.tyut.game.logic.model.Msg
import edu.tyut.game.utils.LogUtils
import edu.tyut.game.utils.StatusBarUtils
import java.io.BufferedOutputStream
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.EOFException
import java.io.IOException
import java.io.InputStreamReader
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.OutputStreamWriter
import java.net.InetSocketAddress
import java.net.Socket
import java.net.SocketTimeoutException
import java.nio.charset.StandardCharsets
import java.util.Collections
import java.util.Timer
import java.util.TimerTask
import kotlin.concurrent.thread

class FlowerActivity : AppCompatActivity() {

    private lateinit var binding: ActivityFlowerBinding

    private lateinit var adapter: MsgAdapter

    private val viewModel by lazy {
        ViewModelProvider(this)[FlowerViewModel::class.java]
    }

    private val socket: Socket = Socket()

    private val tag: String = this.javaClass.name

    // countHandler倒计时
    private var count = 0

    private var isFinished = false

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        binding = ActivityFlowerBinding.inflate(layoutInflater)
        setContentView(binding.root)
        // 隐藏ActionBar
        // 状态栏透明
        // 禁止返回键
        StatusBarUtils.setTranslucentStatusBar(this)

        onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                if (isFinished) {
                    finish()
                }
                else{
                    Toast.makeText(this@FlowerActivity, "请继续游戏，禁止返回😁", Toast.LENGTH_SHORT)
                        .show()
                }
            }
        })


        // 观察三个参数
        viewModel.poemVerseRes.observe(this) { res ->
            val poems = res.getOrNull()
            // LogUtils.d(tag, "所有诗句如下${poems?.size ?: ""}")
            poems?.let {
                LogUtils.d(tag, "获取包含关键字的所有诗句...")
                viewModel.contentSet = it
                LogUtils.d(tag, viewModel.contentSet.toString())
            }
        }
        viewModel.uidRes.observe(this) { res ->
            val flag = res.getOrNull()
            flag?.let {
                Log.d(tag, "游戏成功结束: $flag")
            }
        }
        val sendHandler = SendHandler(Looper.getMainLooper())
        viewModel.isExistRes.observe(this) { res ->
            val isExist = res.getOrNull()
            LogUtils.d(tag, isExist.toString())
            // if (isExist == true){
            //     // 游戏继续
            //     // 存在的话
            //     sendHandler.sendEmptyMessage(SEND_CODE)
            // }else{
            //     // 游戏结束
            //     sendHandler.sendEmptyMessage(SEND_CODE)
            // }
            isExist?.let {
                val message = Message()
                val bundle = Bundle()
                bundle.putBoolean("flag", it)
                message.data = bundle
                message.what = SEND_CODE
                sendHandler.sendMessage(message)
            }
        }
        // 埋点
        viewModel.winRes.observe(this) { res ->
            LogUtils.d(tag, "win埋点: ${res.getOrNull()}")
        }
        viewModel.loseRes.observe(this) { res ->
            LogUtils.d(tag, "lose埋点: ${res.getOrNull()}")
        }

        // 游戏匹配提示
        val dialogOne = AlertDialog.Builder(this)
            .setIcon(R.drawable.image5)
            .setTitle("游戏匹配中😊")
            .setMessage("正在进行游戏匹配...\n匹配计时: 0")
            .setNegativeButton("取消匹配") { dialog, which ->
                run {
                    val dia = dialog as AlertDialog
                    val text = dia.getButton(DialogInterface.BUTTON_NEGATIVE).text
                    // 无论如何退出游戏
                    isFinished = true
                    this.onBackPressedDispatcher.onBackPressed()
                    Log.d(tag, "$text : $which")
                    Toast.makeText(this, "您退出了游戏~", Toast.LENGTH_SHORT).show()
                    dialog.cancel()
                    if (socket.isConnected) {
                        // TODO 发送游戏结束请求
                        viewModel.gameOver(GameApplication.loginUser?.id ?: 0)
                    }
                }
            }
            .create()
        dialogOne.setCancelable(false)
        dialogOne.setCanceledOnTouchOutside(false)
        dialogOne.show()

        val countDownTimer = Timer()
        val countDownHandler = CountDownHandler(Looper.getMainLooper(), dialogOne)
        countDownTimer.schedule(object : TimerTask() {
            override fun run() {
                countDownHandler.sendEmptyMessage(AWAIT_GAME_CODE)
            }
        }, 0, 1000)

        // 发送uid
        // 超时取消游戏
        val cancelHandler = CancelHandler(Looper.getMainLooper(), dialogOne, countDownTimer)
        // 获取飞花令字体，开始游戏
        val timer = Timer()
        val startHandler = StartGameHandler(Looper.getMainLooper(), dialogOne, timer)
        // 获取诗词
        val getContentsByWordHandler = GetContentsByWordHandler(Looper.getMainLooper())
        thread {
            try {
                // socket 连接
                if (!socket.isConnected) {
                    socket.connect(
                        InetSocketAddress(
                            resources.getString(R.string.hostname),
                            resources.getInteger(R.integer.port)
                        ), 10000
                    )
                }
                LogUtils.d(tag, "socket连接成功...")
                val oos = ObjectOutputStream(socket.getOutputStream())
                // 发送uid，游戏结束关闭uid
                val uid = GameApplication.loginUser?.id ?: 0
                oos.writeInt(uid)
                oos.flush()
                // 接受游戏字体，接受飞花令的字
                val ois = ObjectInputStream(socket.getInputStream())
                val info = ois.readUTF()
                LogUtils.d(tag, info)
                val strings = info.split("\\s+".toRegex())
                if (strings.size == 2 && strings[1] == "0x290515") {
                    // TODO 开始游戏
                    LogUtils.d(tag, "游戏开始... ${strings[0]}")
                    countDownTimer.cancel()
                    timer.schedule(object : TimerTask() {
                        override fun run() {
                            val message = Message()
                            val bundle = Bundle()
                            bundle.putString("word", strings[0])
                            message.data = bundle
                            message.what = START_GAME_CODE
                            startHandler.sendMessage(message)
                        }
                    }, 0, 1000)
                    // TODO Handler获取诗句
                    val message = Message()
                    val bundle = Bundle()
                    bundle.putString("word", strings[0])
                    message.data = bundle
                    message.what = GET_CONTENTS_BY_WORD_CODE
                    getContentsByWordHandler.sendMessage(message)
                    // 开启接收消息的线程
                    LogUtils.d(tag, "开启接收消息的线程")
                    val receiveHandler = ReceiveHandle(Looper.getMainLooper())
                    thread {
                        LogUtils.d(tag, "receiveHandler...")
                        receiveMessage(receiveHandler)
                    }
                }
                LogUtils.d(tag, "socket连接成功, 游戏用户id为: $uid")
            } catch (e: SocketTimeoutException) {
                // 连接超时弹出对话框
                Log.d(tag, "${e.message} : 等待超时")
                // TODO 这里必须是handler
                cancelHandler.sendEmptyMessage(CANCEL_GAME_CODE)
            } catch (e: IOException) {
                LogUtils.e(tag, e.message.toString())
            }
        }


        val layoutManager = LinearLayoutManager(this)
        binding.recyclerView.layoutManager = layoutManager
        // 避免重复初始化！！！
        if (!::adapter.isInitialized) adapter = MsgAdapter(viewModel.msgList)
        binding.recyclerView.adapter = adapter
        // 发送msg
        binding.send.setOnClickListener {
            if (!socket.isConnected) {
                Toast.makeText(this, "网络有问题，请重新连接~", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            val content = binding.inputText.text.toString().trim()
            if (content.isNotEmpty()) {
                // 发送消息
                viewModel.isExistPoem(content)
                // adapter.notifyItemInserted(viewModel.msgList.size - 1)
                // // 当有新消息是，刷新RecycleView中的显示
                // binding.recyclerView.scrollToPosition(viewModel.msgList.size - 1)
                // // 将recycleView定位到最后一行
                // binding.inputText.setText("")
            }
        }
    }

    private fun initMsg() {
        val msg1 = Msg("你好 靓仔！！！！", Msg.TYPE_RECEIVED)
        viewModel.msgList.add(msg1)
        val msg2 = Msg("你好 他是谁？？？", Msg.TYPE_SEND)
        viewModel.msgList.add(msg2)
        val msg3 = Msg("这是Tom，很高兴和你谈话！！！！", Msg.TYPE_RECEIVED)
        viewModel.msgList.add(msg3)
        val msg4 = Msg("我也是！！！！", Msg.TYPE_SEND)
        viewModel.msgList.add(msg4)
    }

    private fun sendMessage(message: Msg) {
        try {
            val gson = GsonBuilder().create()
            val oos = BufferedWriter(OutputStreamWriter(socket.getOutputStream()))
            LogUtils.d(tag, message.toString())
            oos.write(gson.toJson(message))
            oos.newLine()
            oos.flush()
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }

    private inner class SendHandler(looper: Looper) : Handler(looper) {
        // MyThread
        override fun handleMessage(msg: Message) {
            if (msg.what == SEND_CODE) {
                val flag = msg.data.getBoolean("flag")
                val content = this@FlowerActivity.binding.inputText.text.toString().trim()
                LogUtils.d(tag, content)
                // 有此句诗词并且未出现过，则成功
                if (!viewModel.contentList.contains(
                        content
                    ) && flag && viewModel.contentSet.contains(content)
                ) {
                    val m = Msg(content, Msg.TYPE_SEND)
                    viewModel.msgList.add(m)
                    viewModel.contentList.add(content)
                    adapter.notifyItemInserted(viewModel.msgList.size - 1)
                    // 当有新消息是，刷新RecycleView中的显示
                    binding.recyclerView.scrollToPosition(viewModel.msgList.size - 1)
                    // 将recycleView定位到最后一行
                    binding.inputText.setText("")
                    // 发送消息
                    thread {
                        this@FlowerActivity.sendMessage(m)
                        LogUtils.d(tag, m.toString())
                    }
                } else {
                    // TODO 此诗词已经出现过宣告游戏结束
                    // 发送游戏结束请求
                    // 禁止发送按钮
                    binding.send.isClickable = false
                    thread {
                        this@FlowerActivity.sendMessage(
                            Msg(
                                "恭喜您，您胜利了，下次再创辉煌🎉！",
                                Msg.TYPE_RECEIVED
                            )
                        )
                    }
                    // 发出弹窗，并提示对方游戏胜利了
                    val dialog = AlertDialog.Builder(this@FlowerActivity)
                        .setIcon(R.drawable.image5) // 设置标题的图片
                        .setTitle("游戏结果😊") // 设置对话框的标题
                        .setMessage("很遗憾，您失败了，再接再厉😊！") // 设置对话框内容
                        .setCancelable(true)
                        .setPositiveButton("游戏结束！") { dialog, which ->
                            // TODO 发送埋点请求，游戏失败
                            viewModel.lose(GameApplication.loginUser?.id ?: 0)
                            Toast.makeText(this@FlowerActivity, "游戏失败", Toast.LENGTH_SHORT)
                                .show()
                            Log.d(tag, "对话框，游戏失败确定按钮: $which")
                            dialog.dismiss()
                            isFinished = true
                            this@FlowerActivity.onBackPressedDispatcher.onBackPressed()
                        }
                        .create()
                    dialog.setCancelable(false)
                    dialog.setCanceledOnTouchOutside(false)
                    dialog.show()
                }
            }
        }
    }

    private fun receiveMessage(handler: Handler) {
        LogUtils.d(tag, "接收消息线程开启...")
        val ois = BufferedReader(InputStreamReader(socket.getInputStream()))
        val gson = Gson()
        while (true) {
            val line = ois.readLine() ?: continue
            LogUtils.d(tag, line)
            val msg = Message()
            val bundle = Bundle()
            bundle.putSerializable("msg", gson.fromJson(line.trim(), Msg::class.java))
            msg.data = bundle
            msg.what = RECEIVE_CODE
            handler.sendMessage(msg)
        }
    }

    private inner class ReceiveHandle(looper: Looper) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            if (msg.what == Companion.RECEIVE_CODE) {
                val m = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    msg.data.getSerializable("msg", Msg::class.java)
                } else {
                    msg.data.getSerializable("msg")
                }
                if (m is Msg) {
                    // 接收到消息
                    LogUtils.d(tag, m.toString())
                    if (m.type == Msg.TYPE_RECEIVED) {
                        // 游戏结束
                        binding.send.isClickable = false
                        // 游戏介绍弹窗
                        val dialog = AlertDialog.Builder(this@FlowerActivity)
                            .setIcon(R.drawable.image5) // 设置标题的图片
                            .setTitle("游戏结果😊") // 设置对话框的标题
                            .setMessage(m.content) // 设置对话框内容
                            .setPositiveButton("游戏结束！") { dialog, which ->
                                // TODO 发送埋点请求，游戏胜利埋点请求
                                viewModel.win(GameApplication.loginUser?.id ?: 0)
                                Toast.makeText(
                                    this@FlowerActivity,
                                    "您点击了确定",
                                    Toast.LENGTH_SHORT
                                ).show()
                                Log.d(tag, "对话框，确定按钮: $which")
                                dialog.dismiss()
                                isFinished = true
                                binding.send.isClickable = false
                                this@FlowerActivity.onBackPressedDispatcher.onBackPressed()
                            }
                            .create()
                        dialog.setCancelable(false)
                        dialog.setCanceledOnTouchOutside(false)
                        dialog.show()
                    } else {
                        m.type = Msg.TYPE_RECEIVED
                        viewModel.msgList.add(m)
                        viewModel.contentList.add(m.content)
                        adapter.notifyItemInserted(viewModel.msgList.size - 1)
                        // 当有新消息是，刷新RecycleView中的显示
                        binding.recyclerView.scrollToPosition(viewModel.msgList.size - 1)
                        // 将recycleView定位到最后一行
                        binding.inputText.setText("")
                    }
                }
            }
        }
    }

    // 加载飞花令游戏的关键词
    private inner class CountDownHandler(
        looper: Looper,
        private val dialog: AlertDialog,
    ) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            if (msg.what == AWAIT_GAME_CODE) {
                dialog.setMessage("正在进行游戏匹配...\n匹配计时: ${count++}")
            }
        }
    }

    // 超时取消游戏
    private inner class CancelHandler(
        looper: Looper,
        private val dialog: AlertDialog,
        private val timer: Timer
    ) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            if (msg.what == CANCEL_GAME_CODE) {
                dialog.setMessage("很抱歉，等待超时😅...")
                dialog.getButton(DialogInterface.BUTTON_NEGATIVE).text = "退出游戏"
                timer.cancel()
            }
        }
    }

    // 开始游戏handler
    private inner class StartGameHandler(
        looper: Looper,
        private val dialog: AlertDialog,
        private val timer: Timer
    ) : Handler(looper) {
        private var count = 0
        override fun handleMessage(msg: Message) {
            val word = msg.data.getString("word")
            if (msg.what == START_GAME_CODE) {
                dialog.setMessage("本局飞花令游戏的词为：【$word】\n正在加载数据中请等待: ${count++}s")
                // LogUtils.d(tag, "$count ${viewModel.contentSet.size}")
                // 至少等待10秒
                if (count > 10 && viewModel.contentSet.isNotEmpty()) {
                    dialog.dismiss()
                    timer.cancel()
                }
                // 发送请求
            }
        }
    }

    // getContentsByWordHandler
    private inner class GetContentsByWordHandler(looper: Looper) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            if (msg.what == GET_CONTENTS_BY_WORD_CODE) {
                val words = msg.data.getString("word")
                words?.let {
                    viewModel.getContentsByWord(it)
                }
            }
        }
    }

    // perfect完美
    companion object {
        fun actionStart(context: Context) {
            val intent = Intent(context, FlowerActivity::class.java)
            context.startActivity(intent)
        }

        private const val SEND_CODE: Int = 0x0001
        private const val RECEIVE_CODE: Int = 0x0002
        private const val START_GAME_CODE: Int = 0x0003
        private const val AWAIT_GAME_CODE: Int = 0x0004
        private const val CANCEL_GAME_CODE: Int = 0x0005
        private const val GET_CONTENTS_BY_WORD_CODE: Int = 0x0006
    }
}